<?php

declare(strict_types=1);

namespace app\controller\system;

use app\BaseController;
use app\model\SysConfig;
use app\service\factory\ResponseFactory;
use app\service\sys\ConfigService;
use app\validate\system\SysConfigValidate;
use InvalidArgumentException;
use think\Response;
use Throwable;

class Config extends BaseController
{
    public function index(ConfigService $configService): Response
    {
        try {
            $page = max(1, (int) $this->request->param('page', 1));
            $pageSize = (int) $this->request->param('page_size', 20);
            $pageSize = $pageSize > 0 ? min($pageSize, 100) : 20;
            $keyword = trim((string) $this->request->param('keyword', ''));

            $query = SysConfig::order(['id' => 'desc']);
            $conditions = $this->buildQueryMap([
                'ignore_fields' => ['page', 'page_size', 'keyword'],
                'like_fields' => ['config_key', 'description', 'category'],
                'in_fields' => ['status'],
            ]);

            if (!empty($conditions)) {
                $query->where($conditions);
            }

            if ($keyword !== '') {
                $query->where(static function ($subQuery) use ($keyword) {
                    $subQuery->whereLike('config_key', '%' . $keyword . '%')
                        ->whereOr('description', 'like', '%' . $keyword . '%')
                        ->whereOr('category', 'like', '%' . $keyword . '%');
                });
            }

            /** @var \think\Paginator $paginator */
            $paginator = $query->paginate([
                'list_rows' => $pageSize,
                'page' => $page,
            ]);

            $items = array_map(
                static fn(SysConfig $config) => $configService->format($config),
                $paginator->items()
            );

            $categories = SysConfig::distinct()->column('category');

            $total = (int) $paginator->total();
            $extra = [
                'categories' => array_values(array_filter(
                    array_unique($categories),
                    static fn($value) => $value !== null && $value !== ''
                )),
            ];

            return json(ResponseFactory::paginated(
                $items,
                $total,
                $page,
                $pageSize,
                'success',
                $extra
            ));
        } catch (Throwable $e) {
            return json(ResponseFactory::error($e->getMessage(), $e->getCode() ?: 500));
        }
    }

    public function save(ConfigService $configService): Response
    {
        try {
            $payload = $this->request->only([
                'config_key',
                'config_value',
                'value_type',
                'description',
                'category',
                'status',
            ], 'post');

            $this->validate($payload, SysConfigValidate::class . '.create');

            $config = $configService->create($payload);

            return json(ResponseFactory::success($configService->format($config), '配置已创建'));
        } catch (InvalidArgumentException $e) {
            return json(ResponseFactory::error($e->getMessage(), 422));
        } catch (Throwable $e) {
            return json(ResponseFactory::error($e->getMessage(), $e->getCode() ?: 500));
        }
    }

    public function read(int $id, ConfigService $configService): Response
    {
        try {
            /** @var SysConfig|null $config */
            $config = SysConfig::find($id);
            if (!$config) {
                return json(ResponseFactory::error('配置不存在', 404));
            }

            return json(ResponseFactory::success($configService->format($config)));
        } catch (Throwable $e) {
            return json(ResponseFactory::error($e->getMessage(), $e->getCode() ?: 500));
        }
    }

    public function update(int $id, ConfigService $configService): Response
    {
        try {
            /** @var SysConfig|null $config */
            $config = SysConfig::find($id);
            if (!$config) {
                return json(ResponseFactory::error('配置不存在', 404));
            }

            $payload = $this->request->only([
                'config_value',
                'value_type',
                'description',
                'category',
                'status',
            ], 'put');

            if ($payload === []) {
                return json(ResponseFactory::error('没有任何可更新的字段', 422));
            }

            $payload['id'] = $id;
            $this->validate($payload, SysConfigValidate::class . '.update');

            $updated = $configService->update($config, $payload);

            return json(ResponseFactory::success($configService->format($updated), '配置已更新'));
        } catch (InvalidArgumentException $e) {
            return json(ResponseFactory::error($e->getMessage(), 422));
        } catch (Throwable $e) {
            return json(ResponseFactory::error($e->getMessage(), $e->getCode() ?: 500));
        }
    }

    public function delete(int $id, ConfigService $configService): Response
    {
        try {
            /** @var SysConfig|null $config */
            $config = SysConfig::find($id);
            if (!$config) {
                return json(ResponseFactory::error('配置不存在', 404));
            }

            if (!$configService->delete($config)) {
                return json(ResponseFactory::error('删除失败', 500));
            }

            return json(ResponseFactory::success(true, '配置已删除'));
        } catch (Throwable $e) {
            return json(ResponseFactory::error($e->getMessage(), $e->getCode() ?: 500));
        }
    }

}
